package com.base.service.workflow.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.base.core.framework.sql.service.impl.SqlBaseServiceImplV1Ext;
import com.base.core.head.enums.TaskTypeEnum;
import com.base.service.workflow.bo.DeploymentBO;
import com.base.service.workflow.bo.DeploymentBO.SequenceFlowBO;
import com.base.service.workflow.bo.DeploymentBO.UserTaskBO;
import com.base.service.workflow.dao.DeploymentDao;
import com.base.service.workflow.entity.DeploymentDO;
import com.base.service.workflow.entity.SequenceFlowDO;
import com.base.service.workflow.entity.TaskDO;
import com.base.service.workflow.service.DeploymentService;
import com.base.service.workflow.service.SequenceFlowService;
import com.base.service.workflow.service.TaskService;
import com.gitee.magic.context.ConverterEditorUtils;
import com.gitee.magic.core.json.JsonObject;

/**
 * 
 * @author start
 *
 */
@Service("deploymentService")
public class DeploymentServiceImpl extends SqlBaseServiceImplV1Ext<DeploymentDO,Long> 
implements DeploymentService {

	@SuppressWarnings("unused")
	private DeploymentDao deploymentDao;
	@Autowired
	private TaskService taskService;
	@Autowired
	private SequenceFlowService sequenceFlowService;
	
	public DeploymentServiceImpl(@Qualifier("deploymentDao")DeploymentDao deploymentDao) {
		super(deploymentDao);
		this.deploymentDao=deploymentDao;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void deploy(String name, String content) {
		DeploymentBO data=ConverterEditorUtils.restoreObject(DeploymentBO.class, new JsonObject(content));
		DeploymentDO deployment = loadByProcessKey(data.getKey());
        if (deployment==null) {
        	deployment = new DeploymentDO();
            deployment.setProcessKey(data.getKey());
        }
        deployment.setName(name);
        deployment.setContent(data);
        save(deployment);

        List<TaskDO> tasks=new ArrayList<>();
        
        for(String gn:data.getExclusiveGateway()) {
        	TaskDO task = new TaskDO();
            task.setDeploymentId(deployment.getId());
            task.setTaskType(TaskTypeEnum.EXCLUSIVE_GATEWAY);
            task.setName(gn);
            task.setLabel(TaskTypeEnum.EXCLUSIVE_GATEWAY.name());
            tasks.add(task);
        }
        
        for(UserTaskBO userTask:data.getUserTask()) {
        	TaskDO task = new TaskDO();
            task.setDeploymentId(deployment.getId());
            task.setTaskType(TaskTypeEnum.USER_TASK);
            task.setName(userTask.getName());
            task.setLabel(userTask.getLabel());
            task.setData(userTask.getData());
            tasks.add(task);
        }
        
		TaskDO task = new TaskDO();
		task.setDeploymentId(deployment.getId());
		task.setTaskType(TaskTypeEnum.START_EVENT);
		task.setName(data.getStartEvent());
		task.setLabel("start");
        tasks.add(task);
        
        task = new TaskDO();
        task.setDeploymentId(deployment.getId());
        task.setTaskType(TaskTypeEnum.END_EVENT);
		task.setName(data.getEndEvent());
        task.setLabel("end");
        tasks.add(task);
        
        taskService.saveBatch(tasks);
        
        Map<String,Long> taskMap=tasks.stream().collect(Collectors.toMap(TaskDO::getName, TaskDO::getId));
		for(SequenceFlowBO flow:data.getSequenceFlow()) {
			SequenceFlowDO sequenceFlow = new SequenceFlowDO();
            sequenceFlow.setLabel(flow.getLabel());
            sequenceFlow.setDeploymentId(deployment.getId());
            sequenceFlow.setSourceRefId(taskMap.get(flow.getSourceRef()));
            sequenceFlow.setTargetRefId(taskMap.get(flow.getTargetRef()));
            sequenceFlow.setExpression(flow.getExpression());
            sequenceFlowService.save(sequenceFlow);
		}
	}

	@Override
	public DeploymentDO loadByProcessKey(String processKey) {
		return load("processKey",processKey);
	}

}
